package org.formal.system.shiro.manager;

import java.util.List;
import javax.annotation.Resource;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.formal.system.entity.ResourceEntity;
import org.formal.system.entity.RoleEntity;
import org.formal.system.entity.UserEntity;
import org.formal.system.service.ResourceService;
import org.formal.system.service.UserService;
import org.springframework.stereotype.Service;

/**
 * 
 * @author jiangyan
 *
 */
@Service
public class SimpleRealm extends AuthorizingRealm{

	@Resource
	private UserService userService;

	@Resource
	private ResourceService resourceService;
	
	/**
	 * 认证信息，主要针对用户登录
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
		String password = PasswordHelper.encryptPassword(
				String.valueOf(token.getPassword()), token.getUsername());
		UserEntity	user = userService.login(token.getUsername(), password);
		if(user == null) {
			throw new AccountException("帐号或密码不正确！");
		}
		else if(!user.getIsOpen()) {
			// 帐号锁定
			throw new LockedAccountException("帐号锁定"); 
		}
		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
				user, 
				user.getPassword(),
				ByteSource.Util.bytes(user.getLoginName()),
				getName() 
				);
		// 当验证都通过后，把用户信息放在session里
		Session session = TokenManager.getSession();
		session.setAttribute("user", user);
		session.setAttribute("userId", user.getId());
		if(user.getRoleList().size() > 0) {
			session.setAttribute("roleId",user.getRoleList().get(0).getId());
		}
		List<ResourceEntity> resources = resourceService.loadUserResources();
		session.setAttribute("resources", resources);
		this.doGetAuthorizationInfo(authenticationInfo.getPrincipals());
		return authenticationInfo;
	}


	/**
	 * 授权
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		this.clearCachedAuthenticationInfo(principals);
		UserEntity user = (UserEntity) principals.getPrimaryPrincipal();
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		List<RoleEntity> roles = user.getRoleList();
		if(roles.size() > 0){
			List<ResourceEntity> resources = resourceService.loadUserResources();
			for(ResourceEntity resource :resources){
				info.addStringPermission(resource.getUrl());
			}
		}
		return info;
	}
	
	public void clearCachedAuthorization(PrincipalCollection principals){
		this.clearCachedAuthorizationInfo(principals);
	}
}
